一直到現在,我們用的 Component 都是長這個樣子:
<app-root></app-root><app-homepage></app-homepage><app-login></app-login>
只有用 Component 的 selector 來使用元件,卻沒有用到其他的屬性。
但如果我想要將資料傳到 Component 內,或是我有兩個或以上的 Component 要互相溝通,我可以怎麼做呢?
在 Componnent 的 template 中我們可以用各種 binding 的方式,與 ts 綁定事件、變數等等:
<input type="submit" [value]="text">
<button (click)="onClick()"> button </button>
...
但是一旦出了這個 Component後,我們就沒有 value ,也沒有 click 這些屬性可以用了,這時候我們就可以用 @Input、@Output 來幫助我們在 Component 間傳遞資料。
那麼我現在設計兩個 Component,AccountManagerComponent 和 LoginComponent,做一個假的簡單的登入系統。將LoginComponent 的標籤 <app-login> 放進 AccountManagerComponent 的 Template 中。目前兩個元件的關係是這樣的,我們稱之為父元件和子元件:
然後我要定義一些變數,在 account-manager.component.ts 宣告變數 status,控制目前是登入或是登出的狀態。我自己定義登入是 true,未登入是 false,所以我初始化就設定為 false:
// account-manager.component.ts
status = false;
在 login.component.ts 宣告變數 loginStatus,用來控制 template 顯示的內容,並且在前面加上 @Input()。其實跟一般的變數宣告一樣,只是前面加上 @Input() 這個 Decorator 而已。
// login.component.ts
@Input() loginStatus;
加上 @Input() 的這個動作,你可以想像成,為這個 Component 定義一個對外的入口、介面,父元件可以透過這個入口傳資料進來。
那記得使用 @Input() 時,要將 Input import 進來。
這樣我們就能使用剛剛宣告的 @Input() loginStatus 來做 Property binding 了,我將 account-manager.component.ts 的 status ,用 Property binding 的方式傳進 <app-login> 的 loginStatus。
// account-manager.component.html
<app-login [loginStatus]="status"></app-login>
當 <app-login> 透過 @Input() 接到從 loginStatus 送進來的值之後,login.component.html 就會因為 loginStatus 修改 DOM。
下面是我搭配 *ngIf 寫的簡單範例:
兩個 <div> 分別指定條件為 loginStatus 和 !loginStatus,只會同時顯示其中一個 <div>。
順便印出 {{loginStatus}}。
// login.component.html
{{loginStatus}}
<div *ngIf="!loginStatus">
帳號 <input type="text"><br>
密碼 <input type="password"><br>
<input type="submit" value="Login">
</div>
<div *ngIf="loginStatus">
<button>Logout</button>
</div>
status = false;

status = true;

那麼就完成了一個父元件到子元件的資料傳遞。整個資料流大致上是這樣: